﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;

namespace FRW.Common.Extensions
{
    /// <summary>
    /// Extensions for the DateTime object
    /// </summary>
    public static class DateTimeExtension
    {
        /// <summary>
        /// Convert the datetime object into an int representing the equivalent unixtime.
        /// </summary>
        /// <param name="time"></param>
        /// <returns></returns>
        public static int ToUnixTime(this DateTime time)
        {
            DateTime unixBaseTime = new DateTime(1970, 1, 1);

            int unixTimeStamp = (int)(time.ToUniversalTime() - unixBaseTime).TotalSeconds;

            return unixTimeStamp;
        }

        /// <summary>
        /// Returns the start of the month for the datetime object
        /// </summary>
        /// <param name="date"></param>
        /// <returns></returns>
        public static DateTime StartOfMonth(this DateTime date)
        {
            return new DateTime(date.Year, date.Month, 1);
        }

        /// <summary>
        /// Returns the date of the Sunday starting the week for the datetime object.
        /// </summary>
        /// <param name="date"></param>
        /// <returns></returns>
        public static DateTime StartOfWeek(this DateTime date)
        {
            return new DateTime(date.Year, date.Month, date.Day).AddDays(-(int)date.DayOfWeek);
        }

        /// <summary>
        /// Returns the end of the month date for the datetime object
        /// </summary>
        /// <param name="date"></param>
        /// <returns></returns>
        public static DateTime EndOfMonth(this DateTime date)
        {
            return new DateTime(date.Year, date.Month, 1).AddMonths(1).Subtract(new TimeSpan(1, 0, 0, 0));
        }

        /// <summary>
        /// Returns a date in the format YYYYMM for the datetime object
        /// </summary>
        /// <param name="date"></param>
        /// <returns></returns>
        public static string YearMonth(this DateTime date)
        {
            return date.Year.ToString() + date.Month.ToString("00");
        }

        /// <summary>
        /// Determine the numbe of months between two dates, inclusive, for the datetime object.
        /// </summary>
        /// <param name="d0"></param>
        /// <param name="d1"></param>
        /// <returns></returns>
        public static IEnumerable<DateTime> MonthsBetween(this DateTime d0, DateTime d1)
        {
            return Enumerable.Range(0, (d1.Year - d0.Year) * 12 + (d1.Month - d0.Month + 1))
                             .Select(m => new DateTime(d0.Year, d0.Month, 1).AddMonths(m));
        }

        /// <summary>
        /// Return a date in the format YYYYWW for the datetime object
        /// </summary>
        /// <param name="date"></param>
        /// <returns></returns>
        public static string YearWeek(this DateTime date)
        {
            CultureInfo current = System.Globalization.CultureInfo.CurrentCulture;
            CultureInfo myCI = new CultureInfo("en-US");
            Calendar myCal = myCI.Calendar;
            CalendarWeekRule myCWR = myCI.DateTimeFormat.CalendarWeekRule;
            DayOfWeek myFirstDOW = myCI.DateTimeFormat.FirstDayOfWeek;

            return date.Year.ToString() + myCal.GetWeekOfYear(date, myCWR, myFirstDOW).ToString("00");
        }

        /// <summary>
        /// Determine if the datetime object is between two specified dates
        /// </summary>
        /// <param name="date"></param>
        /// <param name="startDate"></param>
        /// <param name="endDate"></param>
        /// <returns></returns>
        public static bool IsBetweenDates(this DateTime date, DateTime startDate, DateTime endDate)
        {
            if (date > startDate && date < endDate)
            {
                return (true);
            }

            return false;
        }
    }
}
